/*
 * Copyright (C) 2011 Project R'yleh Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.Arkham;

import android.graphics.Bitmap;


public class Character extends Actor
{
    private String   name;
    private String   worstFear;
    private int      level;
    private int      experience;
    private Stats    baseStats = new Stats();
    private Stats    equipmentMods = new Stats();
    private Stats    equippedStats = new Stats();
    private Item[]   equipment = new Item[Constants.EQUIPPABLE_AREAS];
    private Actor    sprite;
    private int      spriteId;
    
    public Character(){
        name           = "";
        worstFear      = "";
        level          = 0;
        experience     = 0;
        baseStats = new Stats();
        equipmentMods = new Stats();
        equippedStats = new Stats();
        for(int i=0; i<Constants.EQUIPPABLE_AREAS; i++)
        	equipment[i] = Armory.None;

    }
    
    public void setActor(Actor actor){
    	sprite = actor;
    }
    
    public Actor getSprite(){
    	return sprite;
    }

    public void setSpriteId(int id){
    	spriteId = id;
    }
    
    public int getSpriteId(){
    	return spriteId;
    }
    
	public void newGame(){
        name           = "";
        worstFear      = "";
        level          = 1;
        experience     = 0;
        
        baseStats.setStrength(3);
        baseStats.setAgility(3);
        baseStats.setVitality(3);
        baseStats.setMagic(3);
        
        recalculateBaseCalculatedStats();
        
        baseStats.setMaxHealth(30);
        baseStats.setCurrentHealth(30);
        equippedStats.setCurrentHealth(30);
        

        baseStats.setMaxMagic(10);
        baseStats.setCurrentMagic(10);
        equippedStats.setCurrentMagic(10);
        
        for(int i=0; i<Constants.EQUIPPABLE_AREAS; i++)
        	equipment[i] = Armory.None;
        
        recalculateAllEquippedStats();	
    }
	
	public void RandomizeMonster(int Lvl, String Name, Actor Sprite){
		newGame();
		
		while( level < Lvl){
			gainALevel();
		}
		
		name = Name;
		sprite = Sprite;
		
        recalculateBaseCalculatedStats();
        recalculateAllEquippedStats();	
	}
	
	public void newLvl1Char(){
        name           = "";
        worstFear      = "";
        level          = 1;
        experience     = 0;
        
        baseStats.setStrength(3);
        baseStats.setAgility(3);
        baseStats.setVitality(3);
        baseStats.setMagic(3);
        
        recalculateBaseCalculatedStats();
        
        baseStats.setMaxHealth(30);
        baseStats.setCurrentHealth(30);
        equippedStats.setCurrentHealth(30);
        

        baseStats.setMaxMagic(10);
        baseStats.setCurrentMagic(10);
        equippedStats.setCurrentMagic(10);
        
        for(int i=0; i<Constants.EQUIPPABLE_AREAS; i++)
        	equipment[i] = Armory.None;
        
        recalculateAllEquippedStats();		
	}

	public void newLvl2Char(){
		newLvl1Char();
        level          = 2;
        experience     = 100;
        
        int newSTR = baseStats.getStrength() + (int)(Math.random()*4);
        int newAGI = baseStats.getAgility() + (int)(Math.random()*4);
        int newVIT = baseStats.getVitality() + (int)(Math.random()*4);
        int newMAG = baseStats.getMagic() + (int)(Math.random()*4);
        
        baseStats.setStrength(newSTR);
        baseStats.setAgility(newAGI);
        baseStats.setVitality(newVIT);
        baseStats.setMagic(newMAG);
        
        recalculateBaseCalculatedStats();
        
        int newHP = baseStats.getMaxHealth() + (int)(Math.random()* 6) + 5;
        
        baseStats.setMaxHealth(newHP);
        baseStats.setCurrentHealth(newHP);
        equippedStats.setCurrentHealth(newHP);
        
        int newMP = baseStats.getMaxMagic() + (int)(Math.random()* 4) + 2;
        
        baseStats.setMaxMagic(newMP);
        baseStats.setCurrentMagic(newMP);
        equippedStats.setCurrentMagic(newMP);
        
        recalculateAllEquippedStats();		
	}
	
	public void newLvl3Char(){
		newLvl2Char();
        level          = 3;
        experience     = 250;
        
        int newSTR = baseStats.getStrength() + (int)(Math.random()*4);
        int newAGI = baseStats.getAgility() + (int)(Math.random()*4);
        int newVIT = baseStats.getVitality() + (int)(Math.random()*4);
        int newMAG = baseStats.getMagic() + (int)(Math.random()*4);
        
        baseStats.setStrength(newSTR);
        baseStats.setAgility(newAGI);
        baseStats.setVitality(newVIT);
        baseStats.setMagic(newMAG);
        
        recalculateBaseCalculatedStats();
        
        int newHP = baseStats.getMaxHealth() + (int)(Math.random()* 6) + 5;
        
        baseStats.setMaxHealth(newHP);
        baseStats.setCurrentHealth(newHP);
        equippedStats.setCurrentHealth(newHP);
        
        int newMP = baseStats.getMaxMagic() + (int)(Math.random()* 4) + 2;
        
        baseStats.setMaxMagic(newMP);
        baseStats.setCurrentMagic(newMP);
        equippedStats.setCurrentMagic(newMP);
        
        recalculateAllEquippedStats();			
	}	
	
    public int[] getBaseStats(){
    	return baseStats.getStatsArray();
    }
    
    public Stats getEquippedStats(){
    	return equippedStats;
    }
    
    public void changeName(String newName){
        name = newName;
    }
    
    public void changeWorstFear(String newWorstFear){
    	worstFear = newWorstFear;
    }
    
    public String getName(){
  	  return name;  
    }
    
    public String getWorstFear(){
  	  return worstFear;
    }
    
    public void setEXP(int exp){
    	experience=exp;
    }
    
    public void setLevel(int lvl){
    	level=lvl;
    }
    
    public void gainEXP(int exp){
    	experience += exp;
    }
    
    public int getExperience(){
    	return experience;
    }

    public void gainALevel(){
    	level++;
    	
        int newSTR = baseStats.getStrength() + (int)(Math.random()*4);
        int newAGI = baseStats.getAgility() + (int)(Math.random()*4);
        int newVIT = baseStats.getVitality() + (int)(Math.random()*4);
        int newMAG = baseStats.getMagic() + (int)(Math.random()*4);
        
        baseStats.setStrength(newSTR);
        baseStats.setAgility(newAGI);
        baseStats.setVitality(newVIT);
        baseStats.setMagic(newMAG);
        
        recalculateBaseCalculatedStats();
        
        int newHP = baseStats.getMaxHealth() + (int)(Math.random()* 6) + 5;
        
        baseStats.setMaxHealth(newHP);
        baseStats.setCurrentHealth(newHP);
        equippedStats.setCurrentHealth(newHP);
        
        int newMP = baseStats.getMaxMagic() + (int)(Math.random()* 4) + 2;
        
        baseStats.setMaxMagic(newMP);
        baseStats.setCurrentMagic(newMP);
        equippedStats.setCurrentMagic(newMP);
        
        recalculateAllEquippedStats();	
    }
    
    public int getLevel(){
    	return level;
    }
    
    //////////////////////////
    //BASE STAT CALCULATIONS//
    //////////////////////////
    public void calculateBaseAttackPower(){
    	/* CALCULATED Attack Power
    	 * ----------------
    	 * Attack_POWER:
    	 *    Bare Fist:  Strength/2
    	 */
    	baseStats.setAttackPower(baseStats.getStrength()/2);
    }
    
    public void calculateBaseHitPercentage(){
    	/* CALCULATED Hit %
    	 * ----------------
    	 *   Agility/4 + Weapon hit % (L+R hands for duel weidling)
    	 *   Bare Hands weapons are 80%
    	 */
    	baseStats.setHitPercentage( baseStats.getAgility()/4 + 80 );
    }
    
    public void calculateBaseDefense(){
    	/* CALCULATED STATS
    	 * ----------------
    	 * Defense:
    	 *   Vitality/2 + Armor
    	 */
    	baseStats.setDefense(baseStats.getVitality()/2);
    }
    
    public void calculateBaseEvade(){
    	/* CALCULATED Evade
    	 * ----------------
    	 *    Agility/4
    	 */
    	baseStats.setEvade(baseStats.getAgility()/4);
    }
    
    public void calculateBaseMagicDefense(){
    	/* CALCULATED Magical Defense
    	 * ----------------
    	 *    Armor Bonuses Only
    	 *    Base of 0
    	 */
    	baseStats.setMagicDefense(0);
    }
    
    public void calculateBaseMagicEvade(){
    	/* CALCULATED Magical Evade
    	 * ----------------
    	 *     75% of Magic
    	 */
    	baseStats.setMagicEvade((int)(baseStats.getMagic()*.75));
    }
   
    public void recalculateBaseCalculatedStats(){
        calculateBaseAttackPower();
        calculateBaseHitPercentage();
        calculateBaseDefense();
        calculateBaseEvade();
        calculateBaseMagicDefense();
        calculateBaseMagicEvade();
    }

    ////////////////////////
    //EQUIPED CALCULATIONS//
    ////////////////////////
    
    public void calculateEqippedStrength(){
    	equippedStats.setStrength(baseStats.getStrength() + equipmentMods.getStrength());
    }
    
    public void calculateEqippedAgility(){
    	equippedStats.setAgility(baseStats.getAgility() + equipmentMods.getAgility());    	
    }
    
    public void calculateEquippedVitality(){
    	equippedStats.setVitality(baseStats.getVitality() + equipmentMods.getVitality());
    }
    
    public void calculateEquippedMagic(){
    	equippedStats.setMagic(baseStats.getMagic() + equipmentMods.getMagic());
    }
    
    public void calculateEquippedMaxHealth(){
    	equippedStats.setMaxHealth(baseStats.getMaxHealth() + equipmentMods.getMaxHealth());
    }
    
    public void calculateEquippedMaxMagic(){
    	equippedStats.setMaxMagic(baseStats.getMaxMagic() + equipmentMods.getMaxMagic());
    }
    
    public void caclulateEquippedAttackPower(){
    	/* CALCULATED Attack Power
    	 * ----------------
    	 * Attack_POWER:
    	 *    Bare Fist:  Strength/2
    	 *    One Weapon: Strength/4 + Weapon Power
    	 *    Two Weapon: Strength/2 + Both Weapon Powers  [done in equipmentMods area]
    	 */
    	calculateEqippedStrength();
    	if (equipment[Constants.L_HAND] == null && equipment[Constants.R_HAND] == null)
    		equippedStats.setAttackPower(equippedStats.getStrength()/2);
    	else if (equipment[Constants.L_HAND] != null && equipment[Constants.R_HAND]!= null)
    		equippedStats.setAttackPower(equippedStats.getStrength()/2 + equipmentMods.getAttackPower());
    	else
    		equippedStats.setAttackPower(equippedStats.getStrength()/4 + equipmentMods.getAttackPower());
    }
    
    public void calculateEquippedHitPercentage(){
    	/* CALCULATED Hit %
    	 * ----------------
    	 *   Agility/4 + Weapon hit % (Average for Duel Wielding)
    	 *   Bare Hands weapons are 80%
    	 */
    	calculateEqippedAgility();
    	if (equipment[Constants.L_HAND] == null && equipment[Constants.R_HAND] == null)
    		equippedStats.setHitPercentage( equippedStats.getAgility()/4 + 80 );
    	else
    		equippedStats.setHitPercentage(equippedStats.getAgility()/4 + equipmentMods.getHitPercentage());
    }
    
    public void calculateEquippedDefense(){
    	/* CALCULATED STATS
    	 * ----------------
    	 * Defense:
    	 *   Vitality/2 + Armor
    	 */
    	calculateEquippedVitality();
    	equippedStats.setDefense(equippedStats.getVitality()/2 + equipmentMods.getDefense());
    }
    
    public void calculateEquippedEvade(){
    	/* CALCULATED Evade
    	 * ----------------
    	 *    Agility/4
    	 */
    	calculateEqippedAgility();
    	equippedStats.setEvade(equippedStats.getAgility()/4 + equipmentMods.getEvade());
    }
    
    public void calculateEquippedMagicDefense(){
    	/* CALCULATED Magical Defense
    	 * ----------------
    	 *    Armor Bonuses Only
    	 */
    	equippedStats.setMagicDefense(equipmentMods.getMagicDefense());
    }
    
    public void calculateEquippedMagicEvade(){
    	/* CALCULATED Magical Evade
    	 * ----------------
    	 *     75% of Magic
    	 */
    	calculateEquippedMagic();
    	equippedStats.setMagicEvade((int)(equippedStats.getMagic()*.75) + equipmentMods.getMagicEvade());
    }

    public void recalculateAllEquippedStats(){
    	//calculates all equipped stats.
    	calculateEqippedStrength();
    	calculateEqippedAgility();
    	calculateEquippedVitality();
    	calculateEquippedMagic();
    	calculateEquippedMaxHealth();
    	calculateEquippedMaxMagic();
    	calculateEquippedCurrentHealth();
    	calculateEquippedCurrentMagic();
    	caclulateEquippedAttackPower();
    	calculateEquippedHitPercentage();
    	calculateEquippedDefense();
    	calculateEquippedEvade();
    	calculateEquippedMagicDefense();
    	calculateEquippedMagicEvade();
    }

   /////////////////////
   //EQUIPMENT CONTROL//
   ///////////////////// 
    
   public boolean unequipItem(int location){
	   
	   //if nothing is equipped, do nothing
	   if( equipment[location] == Armory.None )
		  return false;
	
	   Item unequipedItem = equipment[location];
	   int itemStat;
	   
	   itemStat = unequipedItem.getStrengthModifier();
	   if ( itemStat > 0 || itemStat < 0)
		   equipmentMods.setStrength(equipmentMods.getStrength() - itemStat);
	   
	   itemStat = unequipedItem.getAgilityModifier();
	   if ( itemStat > 0 || itemStat < 0)
		   equipmentMods.setAgility(equipmentMods.getAgility() - itemStat);
	   
	   itemStat = unequipedItem.getVitalityModifier();
	   if ( itemStat > 0 || itemStat < 0)
		   equipmentMods.setVitality(equipmentMods.getVitality() - itemStat);
	   
	   itemStat = unequipedItem.getMagicModifier();
	   if ( itemStat > 0 || itemStat < 0)
		   equipmentMods.setMagic(equipmentMods.getMagic() - itemStat);
	   
	   //Attack power is checked specially for dual wielding status at end.
	   
	   itemStat = unequipedItem.getHitPercentageModifier();
	   if ( itemStat > 0 || itemStat < 0)
		   equipmentMods.setHitPercentage(equipmentMods.getHitPercentage() - itemStat);

	   itemStat = unequipedItem.getDefenseModifier();
	   if ( itemStat > 0 || itemStat < 0)
		   equipmentMods.setDefense(equipmentMods.getDefense() - itemStat);
	   	   
	   itemStat = unequipedItem.getEvadeModifier();
	   if ( itemStat > 0 || itemStat < 0)
		   equipmentMods.setEvade(equipmentMods.getEvade() - itemStat);
	   	   
	   itemStat = unequipedItem.getMagicDefenseModifier();
	   if ( itemStat > 0 || itemStat < 0)
		   equipmentMods.setMagicDefense(equipmentMods.getMagicDefense() - itemStat);
	   	   
	   itemStat = unequipedItem.getMagicEvadeModifier();
	   if ( itemStat > 0 || itemStat < 0)
		   equipmentMods.setMagicEvade(equipmentMods.getMagicEvade() - itemStat);
	   	   
	   itemStat = unequipedItem.getMaxHealthModifier();
	   if ( itemStat > 0 || itemStat < 0)
		   equipmentMods.setMaxHealth(equipmentMods.getMaxHealth() - itemStat);
	   	   
	   itemStat = unequipedItem.getMaxMagicModifier();
	   if ( itemStat > 0 || itemStat < 0)
		   equipmentMods.setMaxMagic(equipmentMods.getMaxMagic() - itemStat);
	   	   
	   equipment[location] = Armory.None;
	   recalculateAttackPowerEquipMod();
	   recalculateAllEquippedStats();
	   return true;
   }

   public boolean equipItem(Item equipedItem, int location){
	   
	   //not equippable to this slot. do nothing
	   if( !equipedItem.isEquipable(location) )
		  return false;
	   
	   //if there is something equipped, unequip it
	   if(equipment[location] != Armory.None)
	      unequipItem(location);
	   

	   
	   int itemStat;
	   
	   itemStat = equipedItem.getStrengthModifier();
	   if ( itemStat > 0 || itemStat < 0)
		   equipmentMods.setStrength(equipmentMods.getStrength() + itemStat);
	   
	   itemStat = equipedItem.getAgilityModifier();
	   if ( itemStat > 0 || itemStat < 0)
		   equipmentMods.setAgility(equipmentMods.getAgility() + itemStat);
	   
	   itemStat = equipedItem.getVitalityModifier();
	   if ( itemStat > 0 || itemStat < 0)
		   equipmentMods.setVitality(equipmentMods.getVitality() + itemStat);
	   
	   itemStat = equipedItem.getMagicModifier();
	   if ( itemStat > 0 || itemStat < 0)
		   equipmentMods.setMagic(equipmentMods.getMagic() + itemStat);
	   
	   //Attack power is checked specially for dual wielding status at end.
	   
	   itemStat = equipedItem.getHitPercentageModifier();
	   if ( itemStat > 0 || itemStat < 0)
		   equipmentMods.setHitPercentage(equipmentMods.getHitPercentage() + itemStat);

	   itemStat = equipedItem.getDefenseModifier();
	   if ( itemStat > 0 || itemStat < 0)
		   equipmentMods.setDefense(equipmentMods.getDefense() + itemStat);
	   	   
	   itemStat = equipedItem.getEvadeModifier();
	   if ( itemStat > 0 || itemStat < 0)
		   equipmentMods.setEvade(equipmentMods.getEvade() + itemStat);
	   	   
	   itemStat = equipedItem.getMagicDefenseModifier();
	   if ( itemStat > 0 || itemStat < 0)
		   equipmentMods.setMagicDefense(equipmentMods.getMagicDefense() + itemStat);
	   	   
	   itemStat = equipedItem.getMagicEvadeModifier();
	   if ( itemStat > 0 || itemStat < 0)
		   equipmentMods.setMagicEvade(equipmentMods.getMagicEvade() + itemStat);
	   	   
	   itemStat = equipedItem.getMaxHealthModifier();
	   if ( itemStat > 0 || itemStat < 0)
		   equipmentMods.setMaxHealth(equipmentMods.getMaxHealth() + itemStat);
	   	   
	   itemStat = equipedItem.getMaxMagicModifier();
	   if ( itemStat > 0 || itemStat < 0)
		   equipmentMods.setMaxMagic(equipmentMods.getMaxMagic() + itemStat);
	   	
	   equipment[location] = equipedItem;
	   recalculateAttackPowerEquipMod();
	   recalculateAllEquippedStats();
	   return true;
   }

   private void recalculateAttackPowerEquipMod(){
	   
	   equipmentMods.setAttackPower(0);
	   
	   if(equipment[Constants.R_HAND] != null)
	   {
	      equipmentMods.setAttackPower(equipmentMods.getAttackPower() 
	    		  + equipment[Constants.R_HAND].getAttackPowerModifier());
	   }

	   if(equipment[Constants.L_HAND] != null)
	   {
	      equipmentMods.setAttackPower(equipmentMods.getAttackPower() 
	    		  + equipment[Constants.L_HAND].getAttackPowerModifier());
	   }
	   
	   //check for dual wielding offensive weapons
	   if(equipment[Constants.R_HAND].isItemType(Constants.WEAPON) &&
			   equipment[Constants.L_HAND].isItemType(Constants.WEAPON) )
	   {
		   equipmentMods.setAttackPower((int)(equipmentMods.getAttackPower()/2));
	   }

	   if(equipment[Constants.HEAD] != null)
	   {
	      equipmentMods.setAttackPower(equipmentMods.getAttackPower() 
	    		  + equipment[Constants.HEAD].getAttackPowerModifier());
	   }

	   if(equipment[Constants.BODY] != null)
	   {
	      equipmentMods.setAttackPower(equipmentMods.getAttackPower() 
	    		  + equipment[Constants.BODY].getAttackPowerModifier());
	   }
	   
	   if(equipment[Constants.ARMS] != null)
	   {
	      equipmentMods.setAttackPower(equipmentMods.getAttackPower() 
	    		  + equipment[Constants.ARMS].getAttackPowerModifier());
	   }
	   
	   if(equipment[Constants.FEET] != null)
	   {
	      equipmentMods.setAttackPower(equipmentMods.getAttackPower() 
	    		  + equipment[Constants.FEET].getAttackPowerModifier());
	   }
	   
	   if(equipment[Constants.ACC] != null)
	   {
	      equipmentMods.setAttackPower(equipmentMods.getAttackPower() 
	    		  + equipment[Constants.ACC].getAttackPowerModifier());
	   }
   }

   public void calculateEquippedCurrentHealth(){
	   if(equippedStats.getCurrentHealth() > equippedStats.getMaxHealth())
		   equippedStats.setCurrentHealth(equippedStats.getMaxHealth());
		   
   }
   
   public void calculateEquippedCurrentMagic(){
	   if(equippedStats.getCurrentMagic() > equippedStats.getMaxMagic())
		   equippedStats.setCurrentMagic(equippedStats.getMaxMagic());
   }
	
   public Item whatEquipped(int location){
   	return equipment[location];
   }
   
   
   
}